﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SmartDevice.Connectivity;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Threading;

namespace WindowsPhone.Tools
{

    public class WindowsPhoneDevice : INotifyPropertyChanged
    {
        #region Statics

        /// <summary>
        /// Minimum support build is one of the recent Mango previews and upwards (RTM is 7720)
        /// </summary>
        public const int MIN_SUPPORTED_BUILD_NUMBER = 7600;

        /// <summary>
        /// Retrieve possible devices from CoreCon
        /// </summary>
        /// <returns></returns>
        public static List<Device> GetDevices()
        {
            List<Device> list = new List<Device>();

            DatastoreManager manager = new DatastoreManager(CultureInfo.InvariantCulture.LCID);

            foreach (Platform platform in manager.GetPlatforms())
            {
                // Note: CoreCon 10.0 only seems to support Windows Phone so no filtering is required
                list.AddRange(platform.GetDevices());
            }

            return list;
        }

        #endregion

        #region Properties

        private List<Device> _devices;
        public List<Device> Devices
        {
            get
            {
                if (_devices == null)
                {
                    _devices = GetDevices();

                    // set CurrentDevice to a default
                    if (_devices != null)
                        CurrentDevice = _devices[0];
                }

                return _devices;
            }
            set
            {
                if (_devices != value)
                {
                    _devices = value;

                    NotifyPropertyChanged("Devices");
                }
            }
        }

        private Device _currentDevice;
        public Device CurrentDevice
        {
            get { return _currentDevice; }
            set
            {
                if (_currentDevice != value)
                {
                    _currentDevice = value;

                    NotifyPropertyChanged("CurrentDevice");
                }
            }
        }

        private SystemInfo _systemInfo;
        public SystemInfo SystemInfo
        {
            get { return _systemInfo; }
            set
            {
                if (_systemInfo != value)
                {
                    _systemInfo = value;

                    NotifyPropertyChanged("SystemInfo");
                }
            }
        }

        private bool _connected;
        public bool Connected
        {
            get { return _connected; }
            set
            {
                if (_connected != value)
                {
                    _connected = value;

                    NotifyPropertyChanged("Connected");

                    if (_currentDevice != null)
                    {
                        DeviceType = (_currentDevice.IsEmulator() ? "Emulator" : "Phone");
                    }
                    else
                    {
                        DeviceType = "Unknown";
                    }
                }
            }
        }

        private bool _isError;
        public bool IsError
        {
            get { return _isError; }
            set
            {
                if (_isError != value)
                {
                    _isError = value;

                    NotifyPropertyChanged("IsError");
                }
            }
        }

        private string _statusMessage;
        public string StatusMessage
        {
            get { return _statusMessage; }
            set
            {
                if (_statusMessage != value)
                {
                    _statusMessage = value;

                    NotifyPropertyChanged("StatusMessage");
                }
            }
        }

        private string _deviceType;
        public string DeviceType
        {
            get { return _deviceType; }
            set
            {
                if (_deviceType != value)
                {
                    _deviceType = value;

                    NotifyPropertyChanged("DeviceType");
                }
            }
        }

        private Collection<RemoteApplicationEx> _installedApplications;
        public Collection<RemoteApplicationEx> InstalledApplications
        {
            get { return _installedApplications; }
            set
            {
                if (_installedApplications != value)
                {
                    _installedApplications = value;

                    NotifyPropertyChanged("InstalledApplications");
                }
            }
        }

        private List<RemoteAppIsoStoreItem> _remoteIsoStores;
        public List<RemoteAppIsoStoreItem> RemoteIsoStores
        {
            get { return _remoteIsoStores; }
            set
            {
                if (_remoteIsoStores != value)
                {
                    _remoteIsoStores = value;

                    NotifyPropertyChanged("RemoteIsoStores");
                }
            }
        }

        #endregion

        private Device _connectedDevice = null;

        public WindowsPhoneDevice()
        {
            _devices = GetDevices();

            // set CurrentDevice to a default
            if (_devices != null)
                CurrentDevice = _devices[0];
        }

        public string SetCurrentDevice(string name)
        {
            if (name.ToLower()=="phone")
            {
                CurrentDevice = GetDevices()[0];
                return "Set Device to Phone";
            }

            if(name.ToLower()=="emulator")
            {
                CurrentDevice = GetDevices()[1];
                return "Set Device to Emulator";
            }
            return "Wrong Device Name, Using Phone for Default";
        }

        public bool Connect()
        {
            StatusMessage = "Connecting...";
            if (CurrentDevice != null)
            {
                // we're already connected to this device! :)
                //if (CurrentDevice == _connectedDevice)
                if (CurrentDevice.IsConnected())
                {
                    StatusMessage = "Already connected.";
                    return true;
                }
                else
                {
                    try
                    {
                        // disconnect the existing device
                        if (_connectedDevice != null)
                        {
                            StatusMessage = "连接已存在，正在断开...";
                            _connectedDevice.Disconnect();
                            StatusMessage = "连接已断开";
                        }
                        StatusMessage = "Connecting...";
                        CurrentDevice.Connect();
                        StatusMessage = "Connected";

                        SystemInfo = CurrentDevice.GetSystemInfo();

                        if (SystemInfo.OSBuildNo < MIN_SUPPORTED_BUILD_NUMBER)
                        {
                            throw new Exception("Windows Phone Power Tools only support build " + MIN_SUPPORTED_BUILD_NUMBER + " and above. This device is on " + SystemInfo.OSBuildNo + ".");
                        }
                        _connectedDevice = CurrentDevice;
                        StatusMessage = "Connected Successfully !";

                        Connected = true;
                        IsError = false;

                        RefreshInstalledApps();
                    }
                    catch (Exception ex)
                    {
                        SmartDeviceException smartDeviceEx = ex as SmartDeviceException;

                        if (smartDeviceEx != null)
                        {
                            if (ex.Message == "0x89731811")
                            {
                                StatusMessage = "Error! Device not connected with PC";
                            }
                            else if (ex.Message == "0x89731812")
                            {
                                StatusMessage = "Error! Please use Zune or WPConnect to connect phone and unlock it.";
                            }
                            else
                            {
                                StatusMessage = "Error! Please unlock Phone.";
                            }
                        }
                        else
                        {
                            StatusMessage = ex.Message;
                        }

                        IsError = true;
                        Connected = false;
                        _connectedDevice = null;
                        SystemInfo = null;
                    }
                }         
            }
            else
            {
                StatusMessage = "No device connected with PC";
                IsError = false;
                Connected = false;
                _connectedDevice = null;
                SystemInfo = null;         
            }
            return Connected;
        }

        public void RefreshInstalledApps()
        {
            //RemoteApplicationEx

            Collection<RemoteApplication> installed = CurrentDevice.GetInstalledApplications();

            Collection<RemoteApplicationEx> installedCollection = new Collection<RemoteApplicationEx>();

            foreach (RemoteApplication app in installed)
                installedCollection.Add(new RemoteApplicationEx(app));

            InstalledApplications = installedCollection;

            RefreshRemoteIsoStores();
        }

        private void RefreshRemoteIsoStores()
        {
            List<RemoteAppIsoStoreItem> xapIsoStores = new List<RemoteAppIsoStoreItem>();

            foreach (RemoteApplicationEx app in _installedApplications)
            {
                xapIsoStores.Add(new RemoteAppIsoStoreItem(_currentDevice, app));
            }

            RemoteIsoStores = xapIsoStores;
        }

        # region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String property)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(property));
            }
        }

        #endregion
    }

}
